#ifndef _PCIe_PORT_H
#define _PCIe_PORT_H

#include "PCIe_if.h"

class PCIe_port
: public sc_port<PCIe_if>
{
public:
	PCIe_port(sc_module_name	master_name_,
			  PCIe_id_t			master_id_,
			  PCIe_lane_t		lane_width_)
		: _master_name	(master_name_)
		, _master_id	(master_id_)
		, _lane_width	(lane_width_)
		, _in_use		(false)
		, _hold_time	(0,SC_NS)
		, _release_time	(0,SC_NS)
	{}

	void
	PL_send_symbol(PCIe_symbol_t symbol_)
	{
		(*this)->PL_send_symbol(_master_id, symbol_);
	}

	const bool
	DLL_send_sequence_number_byte(byte seq_num_)
	{
		return (*this)->DLL_send_sequence_number_byte(_master_id, seq_num_);
	}

	const bool
	DLL_send_type_byte(byte type_byte_)
	{
		return (*this)->DLL_send_type_byte(_master_id, type_byte_);
	}

	const bool
	DLL_send_data_byte(byte data_byte_)
	{
		return (*this)->DLL_send_data_byte(_master_id, data_byte_);
	}

	const bool
	DLL_send_CRC_byte(byte CRC_byte_)
	{
		return (*this)->DLL_send_CRC_byte(_master_id, CRC_byte_);
	}

	const bool
	DLL_send_LCRC_byte(byte LCRC_byte_)
	{
		return (*this)->DLL_send_LCRC_byte(_master_id, LCRC_byte_);
	}

	void
	TL_send_header_byte(byte header_byte_)
	{
		(*this)->TL_send_header_byte(_master_id, header_byte_);
	}

	void
	TL_send_data_byte(byte data_byte_)
	{
		(*this)->TL_send_data_byte(_master_id, data_byte_);
	}

	void
	TL_send_ECRC_byte(byte ECRC_byte_)
	{
		(*this)->TL_send_ECRC_byte(_master_id, ECRC_byte_);
	}

	const PCIe_id_t
	get_id() const
	{
		return _master_id;
	}

	const PCIe_lane_t
	lane_width() const
	{
		return _lane_width;
	}

	const bool
	is_in_use() const
	{
		return _in_use;
	}

	const bool
	set_in_use(bool	in_use_)
	{
		bool return_val;

		if (in_use_)
		{
			if (_in_use)
			{
				return_val = false;
			}
			else
			{
				return_val = true;
				_hold_time = sc_time_stamp();
			}
		}
		else
		{
			if (_in_use)
			{
				return_val = true;
				_release_time = sc_time_stamp();
			}
			else
			{
				return_val = false;
			}
		}
		_in_use = in_use_;

		return return_val;
	}

	const sc_time
	check_release_time() const
	{
		return _release_time;
	}

protected:
	sc_module_name	_master_name;
	PCIe_id_t		_master_id;
	PCIe_lane_t		_lane_width;
	bool			_in_use;

	sc_time			_hold_time;
	sc_time			_release_time;
};

#endif
